
//GIT Repo
//https://alex.lorenzo@code.google.com/p/disk-benchmarker-nix/ 
package filetest.filewriter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.UUID;

public class FileWriterThreadObj implements Runnable {
    private static final int ONEGIGABYTEWRITE = 262144;
    private static final int BYTEBUFFER=4096;
    private String uuid = UUID.randomUUID().toString().replaceAll("-", "");
    private long stopTime = 0;
    private long startTime = 0;
    private volatile boolean stopwatchrunning = false;
    private volatile boolean sweep = false;
    private static volatile ConcurrentHashMap  <Integer,String> WriteStats = 
            new ConcurrentHashMap <Integer, String>();
    private FileWriter obj;
    private String fileToWrite;
    private FileOutputStream writeOut;
    private FileChannel writeOutChannel;
    private ByteBuffer writeOutBuffer;
    private Random random = new Random();
    public synchronized boolean isSweep() {
        return sweep;
    }
    public void setSweep(boolean sweep) {
        this.sweep = sweep;
    }
    public String getFileToWrite() {
            return fileToWrite;
    }
    public void setFileToWrite(String fileToWrite) {
            this.fileToWrite = fileToWrite;
    }
    public FileWriterThreadObj(FileWriter obj){
            this.setObj(obj);
            this.setFileToWrite(getObj().getDirectory() + "/"+this.getUUID() + 
                            Thread.currentThread().getId());
    }
    @Override
    public void run() {
        boolean append = true;
        //this.setWriteOut(writeOut,true);
        int randomnumber = 0;
        //The below code writes random files to a bytearray buffer and forces 
        //sync to a file.
        try {
            this.writeOut = new FileOutputStream(this.getFileToWrite()
                                ,append);
        } catch (FileNotFoundException ex){
            ex.printStackTrace();
        }
        this.writeOutBuffer = ByteBuffer.allocate(BYTEBUFFER);
    	while (!this.isStopwatchrunning()){
            this.setSweep(false);
            while (!this.isSweep()){
                for (int i = 0; i < FileWriterThreadObj.ONEGIGABYTEWRITE; i++)
                {
                    randomnumber = this.getRandom().nextInt
                            (FileWriter.getITERATIONS() - 0) + 0;
                    
                    try {
                        byte [] toByteBuffer = 
                                FileWriter.getRandomCharacterString
                                    (randomnumber).getBytes();
                        this.writeOutBuffer = ByteBuffer.wrap(toByteBuffer);
                        this.writeOutChannel = writeOut.getChannel();
                        //Will force the ByteBuffer to dumbp data to disk.
                        this.writeOutChannel.force(true);
                        this.writeOut.getFD().sync();
                        this.writeOutChannel.write(this.writeOutBuffer);
                        this.writeOutBuffer.rewind();
                    } catch (IOException ex) {
                        System.out.println("Error in FileWriterObj class: Could"
                                + " not "
                            + "open file: " + ex + "Printing Stack Trace:\n");
                        ex.printStackTrace(System.err);
                    }
                }
                //The below code clears the file after a certain size is reached.
                    try {
                        this.writeOut = new FileOutputStream(this.getFileToWrite()
                            ,false);
                        byte [] toByteBuffer = "Complete Iteration".getBytes();
                        this.writeOutBuffer = ByteBuffer.wrap(toByteBuffer);
                        this.writeOutChannel.force(true);
                        this.writeOut.getFD().sync();
                        this.writeOutChannel.write(this.writeOutBuffer);
                        this.writeOutChannel.close();
                        this.writeOutBuffer.rewind();
                    } catch (IOException ex) {
                        System.out.println("Error in FileWriterObj class: Could not "
                            + "open file: " + ex + "Printing Stack Trace:\n");
                        ex.printStackTrace(System.err);
                    }
                    this.setSweep(true);
                
                   
            }
        }
        
    }

    public Random getRandom() {
        return random;
    }

    public void startStopWatch(){
        this.startTime = System.nanoTime();
        this.setStopwatchrunning(true);
    }
    public long stopStopwatch(){
        this.stopTime = System.nanoTime();
        this.setStopwatchrunning(false);
        return (this.stopTime - this.startTime);
    }
    public String getUUID(){
        return this.uuid;
    }
    public FileWriter getObj() {
            return obj;
    }
    public void setObj(FileWriter obj) {
            this.obj = obj;
    }
    public static ConcurrentHashMap  <Integer,String> getWriteStats() {
            return WriteStats;
    }
    public static void setWriteStats(ConcurrentHashMap  <Integer,String> writeStats) {
            WriteStats = writeStats;
    }
    public synchronized boolean isStopwatchrunning() {
            return stopwatchrunning;
    }
    public synchronized void setStopwatchrunning(boolean stopwatchrunning) {
            this.stopwatchrunning = stopwatchrunning;
    }
}
